package com.example.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.common.dtos.ResponseResult;
import com.example.user.entity.User;
import com.example.user.entity.dto.UserDto;
import com.example.user.mapper.UserMapper;
import com.example.user.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.utils.RegexUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;


import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

import static com.example.utils.RedisConstants.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 凡哥哥
 * @since 2023-10-16
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private UserMapper userMapper;
    /**
     * 用户登录
     *
     * @param user
     * @return
     */
    @Override
    public ResponseResult login(User user) {
        //1.根据用户名查询数据库用户信息
        String phone = user.getPhone();
        String password = user.getPassword();
        //条件构造器
        LambdaQueryWrapper<User> lqw1 = new LambdaQueryWrapper();
        lqw1.and(q -> q.eq(User::getPhone, phone).eq(User::getPassword,password));
        User user1 = getOne(lqw1);
        //2.判断用户是否存在
        if (user1 == null) {
            //3.不存在，则返回错误信息
            return ResponseResult.errorResult(501,"账号或密码错误");
        }
        //4.存在，随机生成token，作为登陆令牌
        String token = UUID.randomUUID().toString(true);
        //5.将User对象转换为HashMap存储到Redis中
        UserDto userDto = BeanUtil.copyProperties(user1, UserDto.class);
        Map<String, Object> userMap = BeanUtil.beanToMap(userDto, new HashMap<>(),
                CopyOptions.create()
                        .setIgnoreNullValue(true)
                        .setFieldValueEditor((fieldName, fieldValue) -> fieldValue.toString()));
        log.info("userMap:{}",userMap);
        String key = LOGIN_USER_KEY + token;
        stringRedisTemplate.opsForHash().putAll(key,userMap);
        //6.设置token有效期
        stringRedisTemplate.expire(key,LOGIN_USER_TTL, TimeUnit.MINUTES);
        //返回token
        return ResponseResult.okUserOrToken(200,token,user1);
    }

    /**
     * 用户注册
     *
     * @param user
     * @return
     */
    @Override
    public ResponseResult<String> register(User user) {
        //校验手机号
        if(stringRedisTemplate.opsForSet().isMember(REGISTER_PHONE_KEY, user.getPhone())){
            return ResponseResult.errorResult(501,"手机号已注册");
        }
        //从Redis中取出验证码,校验用户输入的验证码是否一致
        Optional<String> codeOptional = Optional.ofNullable(stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + user.getPhone()));
        String code = codeOptional.orElse("null");
        String code1 = user.getCode();
        if (!code.equals(code1)){
            //不一致,返回验证码错误
            return ResponseResult.errorResult(501,"验证码错误");
        }
        //一致,保存用户
        User user1 = new User();
        user1.setPhone(user.getPhone());
        user1.setPassword(user.getPassword());
        this.save(user1);
        //存储手机号到Redis,用于校验是否已注册过
        stringRedisTemplate.opsForSet().add(REGISTER_PHONE_KEY, user.getPhone());
        return ResponseResult.okResult("注册成功");
    }

    /**
     * 用户手机号
     *
     * @param phone
     * @return
     */
    @Override
    public ResponseResult<String> sendCode(String phone) {
        // TODO 发送短信验证码并保存验证码
        //1.校验手机号
        if (RegexUtils.isPhoneInvalid(phone)) {
            //2.如果不符合，返回错误信息
            return ResponseResult.errorResult(500,"手机号格式错误!");
        }
        //3.从缓存中校验手机号是否存在,存在就直接返回错误信息
        if(stringRedisTemplate.opsForSet().isMember(REGISTER_PHONE_KEY, phone)){
            return ResponseResult.errorResult(500,"手机号已注册");
        }
        //4.不存在,则手机号注册用户,生成验证码
        String code = RandomUtil.randomNumbers(6);
        //5.将验证码存入Redis中
        stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY + phone,code,LOGIN_CODE_TTL, TimeUnit.MINUTES);
        //6.给用户发送验证码
        return ResponseResult.okResult(code);
    }

    /**
     * 退出登录token
     *
     * @param token
     */
    @Override
    public void exit(String token) {
        String key = LOGIN_USER_KEY + token;
        stringRedisTemplate.delete(key);
    }

    /**
     * 查询用户信息
     *
     * @param page
     * @param pageSize
     * @param name
     * @return
     */
    @Override
    public ResponseResult<Page> pageInfo(Integer page, Integer pageSize, String name) {
        Page<User> page1 = new Page<>(page,pageSize);
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.eq(User::getIsDelete,1);
        lqw.like(User::getName,name);
        Page<User> userPage = this.page(page1, lqw);
        return ResponseResult.okResult(userPage);
    }

    /**
     * 修改状态
     *
     * @param id@return
     */
    @Override
    public ResponseResult updateStatus(Long id) {
        User user = userMapper.selectById(id);
        if (!user.getStatus()) {
            user.setStatus(true);
        } else {
            user.setStatus(false);
        }
        userMapper.updateById(user);
        return ResponseResult.okResult(user);
    }

    /**
     * 删除
     *
     * @param ids
     * @return
     */
    @Override
    public ResponseResult deleteUsers(int[] ids) {
        for (int id : ids) {
            User user = this.getById(id);
            Boolean status = user.getStatus();
            if (status){
                return ResponseResult.errorResult(500,"用户状态正常不能删除");
            }
            LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(User::getId, id);
            updateWrapper.set(User::getIsDelete, 0);
            this.update(updateWrapper);
        }
        return ResponseResult.okResult("用户删除成功");
    }
}
